﻿/*
 * Создан: Оникийчук Антон Игоревич
 * Компания: ООО "ИМСАТ"
 * Дата создания: 21.01.2009
 * Время создания: 10:03
 * Emal разработчика: onikiychuka@gmail.com
 */
using System;
using System.Xml;
using System.Collections.Generic;
using System.Linq;

namespace IMSAT.OFTD.DOM
{
    /// <summary>
    /// Элемент листа
    /// </summary>
    public class Element : Node
    {
        private readonly LinkConnectionPointCollection _connectionPoits = new LinkConnectionPointCollection();
        private PropertyCollection _attributes;
        private ElementCollection _childElements;
        private string _class = "";
        private ID _id;
        private Layer _layer;
        private Page _page;
        private string _style = "";

        public Element()
        {
            Init();
        }

        /// <summary>
        /// Id элемента - уникальный итендефикктор элемента в документе
        /// </summary>
        public ID Id
        {
            get
            {
                OnDataAsked();
                return _id;
            }
        }
        public string Title
        {
            get
            {
                IEnumerable<string> n =
                    from a in Attributes
                    where a is TextProperty && a.Name == "Наименование"
                    select a.Value;
                string strName = string.Empty;
                try { strName = n.First<string>(); }
                catch { }
                string strId = Id.OriginalId;
                if (strId != string.Empty)
                    strName += "[" + strId + "]";
                return strName;
            }
        }

        /// <summary>
        /// Класс элемента
        /// </summary>
        public string Class
        {
            get
            {
                OnDataAsked();
                return _class;
            }
        }


        /// <summary>
        /// Стиль отображения элемента
        /// </summary>
        public string Style
        {
            get
            {
                OnDataAsked();
                return _style;
            }
            set { _style = value; }
        }


        /// <summary>
        /// Слой на котором находится элемент
        /// </summary>
        public Layer Layer
        {
            get
            {
                OnDataAsked();
                return _layer;
            }
            set { _layer = value; }
        }

        public LinkConnectionPointCollection ConnectionPoits
        {
            get { return _connectionPoits; }
        }

        /// <summary>
        /// Список свойств.
        /// </summary>
        public PropertyCollection Attributes
        {
            get
            {
                OnDataAsked();
                return _attributes;
            }
        }

        /// <summary>
        /// Список дочерних элементов плана
        /// </summary>
        public ElementCollection ChildElements
        {
            get { return _childElements; }
        }

        /// <summary>
        /// Страница на которой находится элемент.
        /// </summary>	 	
        public Page Page
        {
            get { return _page; }
        }

        public void AppendAttribute(Property attribute)
        {
            AppendChild(attribute);
            /*
	 		using(PropertyCollection.NodeCollectionEditingFlag<Property> flg = _attributes.BeginEdit())
	 		{
	 			_attributes.InsertChild(attribute);
	 		}*/
        }

        public Property AppendAttribute(string name)
        {
            throw new NotImplementedException();
            //TODO: Полностью реализовать функцию.
            using (NodeCollection<Property>.NodeCollectionEditingFlag<Property> flg = _attributes.BeginEdit())
            {
                //_attributes.InsertChild(attribute);
            }
        }

        protected virtual void InitConnectionPoints()
        {
        }

        public string Name
        {
            get
            {
                var n =
                    from a in Attributes
                    where a is TextProperty && a.Name == "Наименование"
                    select a.Value;
                try
                {
                    return n.First<string>();
                }
                catch
                {
                    return string.Empty;
                }
            }

        }
        public string GetAttribute(string attributeName)
        {
            var nd = FindFirst((n) => !(n is TextProperty) && n.XmlName == attributeName);
            if (nd == null)
                return string.Empty;
            var prop = nd as Property;
            return prop == null ? string.Empty : prop.Value;
        }
        public string GetTextAttribute(string attributeName)
        {
            var nd = FindFirst((n) => (n is TextProperty) && n.XmlName == attributeName);
            if (nd == null)
                return string.Empty;
            var prop = nd as Property;
            return prop == null ? string.Empty : prop.Value;
        }

        protected virtual void Init()
        {
            InitConnectionPoints();
            _childElements = new ElementCollection(ChildNodes);
            _attributes = new PropertyCollection(ChildNodes);
        }
        public override string ToString()
        {
            return "XName: " + this.XmlName + " ;Title: " + this.Title + " [" + this.Id.OriginalId + "]"; ;
        }

        #region Nested type: ElementAppender

        public abstract class ElementAppender : NodeAppender
        {
            public ElementAppender(Element elem) : base(elem)
            {
            }

            [NonIndex]
            protected Element CurElement
            {
                get { return CurNode as Element; }
            }

            protected ID Id
            {
                get { return CurElement.Id; }
                set { CurElement._id = value; }
            }

            protected string Class
            {
                get { return CurElement.Class; }
                set { CurElement._class = value; }
            }

            protected Page Page
            {
                get { return CurElement.Page; }
                set { CurElement._page = value; }
            }
        }

        #endregion

        #region Nested type: Reader

        public class Reader : NodeXmlReader
        {
            protected override bool CheckReader(XmlReader rd, bool _prevRes, Node parentNode)
            {
                if (_prevRes)
                {
                    if (parentNode == null || !(parentNode is Page))
                        return false;
                    var nspm = new OFTDCommonNamespaceManager();
                    string ns = rd.NamespaceURI;
                    if (ns == nspm.OFTDEditorNamespace.Namespace)
                        return false;
                    if (ns == nspm.OFTDAShapesNamespace.Namespace)
                        return false;
                    if (ns == nspm.OFTDPropertyPlaceNamespace.Namespace)
                        return false;
                    if (ns == nspm.SVGNamespace.Namespace)
                        return false;
                }
                return base.CheckReader(rd, _prevRes, parentNode);
            }

            protected override Node InitNode(XmlReader reader, Node initedNode)
            {
                if (initedNode == null)
                {
                    initedNode = new Element();
                }
                var el = initedNode as Element;
                if (el != null)
                {
                    var id = new ID(reader.GetAttribute("id"), reader.GetAttribute("svg-id"));
                    el._id = id;
                    int cnt = reader.AttributeCount;
                    for (int i = 0; i < cnt; i++)
                    {
                        reader.MoveToAttribute(i);
                        if (reader.LocalName == "class")
                        {
                            el._class = reader.Value;
                        }
                        else if (reader.LocalName == "style")
                        {
                            el._style = reader.Value;
                        }
                        else
                        {
                            var prop = new Property(reader.LocalName,
                                                    new XmlNamespace(reader.NamespaceURI, reader.Prefix));
                            prop.Value = reader.Value;
                            el.AppendAttribute(prop);
                        }
                        reader.MoveToElement();
                    }
                }
                return base.InitNode(reader, initedNode);
            }

            protected override Node InitObjectAfterBuild(Node result)
            {
                return base.InitObjectAfterBuild(result);
            }
        }

        #endregion
    }
}